class WeeklyResult < WeeklyConnect
  belongs_to :weekly
  belongs_to :sp_type
  belongs_to :weekly_result_work

  ['wid', 'name', 'wtype', 'author'].each do |n|
    unless self.column_names.include?(n)
      eval "attr_reader(:#{n});def #{n};@#{n} ||= weekly_result_work.#{n};end"
    end
  end

  def work
    Work.find_by_wid wid
  end

  #0 = 'new'
  #-1 = except
  #>0
  #nil ??
  def last_score_rank unknown_ids = nil
    return nil if unknown_ids && unknown_ids.include?(wid)
    if last_weekly = weekly.last
      return -1 if wid == last_weekly.last.wid
      return 0 if wid > last_weekly.wid
      last_result = WeeklyResult.find_by_wid_and_weekly_id wid, last_weekly.id
      if last_result
        return last_result.score_rank
      else
        last_except = WeeklyExcept.find_by_wid_and_weekly_id wid, last_weekly.id
        return -1 if last_except
        existed_count = WeeklyResult.count :include => :weekly,
                                             :conditions => ['weeklies."index" < ? and weekly_results.wid = ?', weekly.index, wid]
        return (existed_count > 0 ? nil : 0)
      end
    end
    0
  end

  def new_rank_check last_weekly = nil, unknown_ids = nil
    return nil if unknown_ids && unknown_ids.include?(wid)
    last_weekly ||= weekly.last
    if last_weekly
      return 0 if wid > last_weekly.wid
      existed_count = WeeklyResult.count :include => :weekly,
                                           :conditions => ['weeklies."index" < ? and weekly_results.wid = ?', weekly.index, wid]
      return (existed_count > 0 ? nil : 0)
    end
    0
  end

  def is_changqi?
    WeeklyResult.count(:include => :weekly,
      :conditions => ["score_rank <= weeklies.rank_from and weekly_results.wid = ? and weeklies.id < ?", wid, weekly_id
      ]) > 2
  end

  #周刊统计数据
  def self.stat id1, id2, except_ids, stat_type = :all
    time = Time.now
    puts "*reading data..."
    if stat_type == 'simple'
      results1 = Result.find :all, :include => :work,
                           :conditions => ["results.scan_id = ? and clicks > 1000 and works.ac_type_id != 18", id1]
    else
      results1 = Result.find :all, :include => :work,
                           :conditions => ["results.scan_id = ? and works.ac_type_id != 18 and works.status = 1", id1]
    end
    if stat_type == 'some'
      results2 = Result.all :include => :work,
                           :conditions => ["results.scan_id = ? and works.wid in (?)", id2, except_ids]
    else
      results2 = Result.all :include => {:work => :ac_type},
                           :conditions => ["results.scan_id = ? and works.wid not in (?) and works.ac_type_id != 18 and works.status = 1", id2, except_ids]
    end
    puts "#{Time.now - time} seconds passed.."
    results = {}
    results2.each{|r2| results[r2.work.id] = r2}
    unless results1.empty?
      results1.each do |r1|
        if results[r1.work.id]
          results[r1.work.id].clicks -= r1.clicks
          results[r1.work.id].comments -= r1.comments
          results[r1.work.id].stows -= r1.stows.to_i
          results[r1.work.id].danmu -= r1.danmu.to_i
          results[r1.work.id].tj -= r1.tj.to_i
          results[r1.work.id].yb -= r1.yb.to_i
          results[r1.work.id][:old] = true
        end
      end
      puts "#{Time.now - time} seconds passed.."
      #删除错误数据
      last_wid = Result.maximum("works.wid", :include => :work, :conditions => ["scan_id = ?", id1]).to_i
      results_b = results.select{|i, r| !r[:old] && r.work.wid <= last_wid - 5000 }
      results_b.each{|i, r| results.delete(i)}
      results_b1 = results.select{|i, r| !r[:old] && r.work.wid <= last_wid }
      check_results = Result.all(:select => "work_id",
                                  :conditions => ["work_id in (?) and scan_id < ? and clicks > 500", results_b1.collect{|i, r| r.work_id}, id1],
                                  :group => "work_id").collect{|r| r.work.id}
      results_c = results_b1.select{|i, r| check_results.include?(r.work_id)}
      File.open(%[#{Rails.root}/config/_lost_last.yml],"w"){ |io| YAML.dump results_b.collect{|r| r.last} + results_c.collect{|r| r.last},io }
      results_c.each{|i, r| results.delete(i)}
    end
    puts "#{Time.now - time} seconds passed.."
    puts "*computing..." #计算分数
      results.values.each{|r| r[:point] = r.get_ranking_point}
    puts "#{Time.now - time} seconds passed.."
      c_rank = nil
      l_id = nil
      #点击序
      results.values.sort_by{|r| 0 - r.clicks}.each_with_index do |r, i|
        c_rank = i + 1 if i.zero? || results[r.work.id].clicks != results[l_id].clicks
        l_id = r.work.id
        results[r.work.id][:click_rank] = c_rank
      end
    puts "#{Time.now - time} seconds passed.."
      #评论序
      results.values.sort_by{|r| 0 - r.comments}.each_with_index do |r, i|
        c_rank = i + 1 if i.zero? || results[r.work.id].comments != results[l_id].comments
        l_id = r.work.id
        results[r.work.id][:comment_rank] = c_rank
      end
    puts "#{Time.now - time} seconds passed.."
      #收藏序
      results.values.sort_by{|r| 0 - r.stows.to_i}.each_with_index do |r, i|
        c_rank = i + 1 if i.zero? || results[r.work.id].stows != results[l_id].stows
        l_id = r.work.id
        results[r.work.id][:stow_rank] = c_rank
      end
    puts "#{Time.now - time} seconds passed.."
      #弹幕序
      results.values.sort_by{|r| 0 - r.danmu.to_i}.each_with_index do |r, i|
        c_rank = i + 1 if i.zero? || results[r.work.id].danmu != results[l_id].danmu
        l_id = r.work.id
        results[r.work.id][:danmu_rank] = c_rank
      end
    puts "#{Time.now - time} seconds passed.."
      #推荐序
      results.values.sort_by{|r| 0 - r.tj.to_i}.each_with_index do |r, i|
        c_rank = i + 1 if i.zero? || results[r.work.id].tj != results[l_id].tj
        l_id = r.work.id
        results[r.work.id][:tj_rank] = c_rank
      end
    puts "#{Time.now - time} seconds passed.."
      #硬币序
      results.values.sort_by{|r| 0 - r.yb.to_i}.each_with_index do |r, i|
        c_rank = i + 1 if i.zero? || results[r.work.id].yb != results[l_id].yb
        l_id = r.work.id
        results[r.work.id][:yb_rank] = c_rank
      end
    puts "compute over.(#{Time.now - time} sec.)"
      #Point序
      c_rank = 0
	  l_rank = 0
      results.values.sort_by{|r| r[:point]}.reverse.each do |r|
        if r.work.is_in_rank?
          c_rank = l_rank + 1 if c_rank.zero? || results[r.work.id][:point] != results[l_id][:point]
		  l_rank += 1
          l_id = r.work.id
          results[r.work.id][:point_rank] = c_rank
        else
          r.is_hot_bangumi? if c_rank < 40
        end
      end
  end
  
  #收藏率
  def stow_ratio
    format("%.2f", stows * 100.0 / clicks).to_f
  end
  
  #获得所有主榜资料
  def self.main_results object_weekly_id =nil
    if object_weekly_id
      WeeklyResult.all :include => [:weekly, :weekly_result_work],
                       :conditions => ["score_rank <= weeklies.rank_from and weekly_id = ?", object_weekly_id]
    else
      WeeklyResult.all :include => [:weekly, :weekly_result_work],
                       :conditions => ["score_rank <= weeklies.rank_from"]
    end
  end

  #获得所有长期 (wid array)
  def self.all_changqi object_weekly_id
    @@all_changqi ||= {}
    @@all_changqi[object_weekly_id.to_i] ||= WeeklyResult.connection.execute(%[select * from (select count(wrw.wid) as count, wrw.wid as wid from weekly_results wr
join weekly_result_works wrw on wrw.id = wr.weekly_result_work_id join weeklies on weeklies.id = wr.weekly_id
where score_rank <= weeklies.rank_from #{"and wr.weekly_id <= #{object_weekly_id}" if object_weekly_id.to_i > 0} group by wrw.wid)
where count > #{object_weekly_id >= 0 ? 2 : 1 } order by count desc]).collect{|wr| wr["wid"]}
  end

  def self.all_info options
    self.all({:order => "score desc, score_rank", :joins => "wr join weekly_result_works wrw on wrw.id = wr.weekly_result_work_id",
    :select => "wr.id, wr.weekly_id, wr.clicks, wr.clicks_rank, wr.comments, wr.comments_rank,
wr.stows, wr.stows_rank, wr.danmu, wr.danmu_rank, wr.tj, wr.tj_rank, wr.yb, wr.yb_rank, wr.part, wr.sp_type_id, wr.score, wr.score_rank,
wrw.wid as wid, wrw.author as author, wrw.name as name, wrw.wtype as wtype"}.merge options)
  end
end
